﻿using System;
using System.Activities;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Instances.Contracts;
using Microsoft.HomeServer.SDK.Interop.v1;
using System.Runtime.InteropServices;
using Umbrella.Net.Contracts;

namespace Umbrella.Whs.Service
{
    public sealed class UpdateChecker
    {
        private static readonly UpdateChecker _instance = new UpdateChecker();

        public static UpdateChecker Instance
        {
            get { return _instance; }
        }

        private readonly log4net.ILog _log = log4net.LogManager.GetLogger(typeof(UpdateChecker));
        private Timer _timer;
        private object _checkLock = new object();

        public DateTime LastCheck
        {
            get;
            private set;
        }

        public UmbrellaReleaseInfo NewVersion
        {
            get;
            private set;
        }

        private void OnTick(object state)
        {
            try
            {
                DoCheck();
            }
            catch (Exception x)
            {
                _log.Warn("Failed to check for update", x);
            }
        }

        public void DoCheckManually()
        {
            _log.Info("Checking for update manually...");

            try
            {
                DoCheck();
            }
            catch (Exception x)
            {
                _log.Error("Failed to check for update manually", x);

                throw;
            }
        }

        private void DoCheck()
        {
            lock (_checkLock)
            {
                try
                {
                    if (_log.IsDebugEnabled)
                    {
                        _log.DebugFormat(
                            "Checking for update for {0} (#{1})...",
                            UmbrellaVersion.VersionString,
                            UmbrellaVersion.VersionId
                            );
                    }

                    // run the workflow
                    var output = UmbrellaWorkflowInvoker.Invoke(new Workflows.CheckForUpdateOnline());

                    var nv = (UmbrellaReleaseInfo)output["LatestVersionInfo"];

                    if ((nv.ReleaseId > UmbrellaVersion.VersionId))
                        this.NewVersion = nv;
                    else
                        this.NewVersion = null;
	
                    // store this check
                    this.LastCheck = DateTime.Now;
	
                    Properties.States.Default.CheckUpdateLastCheck = this.LastCheck;
	
                    Properties.States.Default.Save();
                }
                catch (Exception e)
                {
                    _log.Error("Failed to check for update", e);

                    throw;
                }
            }
        }

        private UpdateChecker()
        {
            if (_log.IsDebugEnabled)
                _log.Debug("Creating singleton");

            try
            {
                this.NewVersion = new UmbrellaReleaseInfo();

                // load state
                try
                {
                    this.LastCheck = Properties.States.Default.CheckUpdateLastCheck;
                }
                catch
                {
                    _log.Warn("Failed to read CheckUpdateLastCheck state");
	
                    this.LastCheck = DateTime.MinValue;
                }
	
                // initialize update check timer
                _timer = new Timer(
                    new TimerCallback(OnTick),
                    null,
                    1000,
                    (1000 * 60 * Properties.Settings.Default.CheckUpdateIntervalMinutes)
                    );
            }
            catch (Exception e)
            {
                _log.Fatal("Failed to create singleton", e);

                throw;
            }

        }
    }
}